package com.car.loan.project.xr.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.car.loan.common.exception.loan.LoanParameterException;
import com.car.loan.common.utils.StringUtils;
import com.car.loan.common.utils.file.PdfUtil;
import com.car.loan.framework.aspectj.lang.annotation.DataStatus;
import com.car.loan.framework.aspectj.lang.annotation.Log;
import com.car.loan.framework.aspectj.lang.enums.BusinessType;
import com.car.loan.framework.web.domain.AjaxResult;
import com.car.loan.project.cm.domain.CmBank;
import com.car.loan.project.cm.mapper.CmBankMapper;
import com.car.loan.project.xr.domain.LoanDetail;
import com.car.loan.project.xr.domain.LoanExt;
import com.car.loan.project.xr.domain.LoanStatus;
import com.car.loan.project.xr.mapper.LoanDetailMapper;
import com.car.loan.project.xr.mapper.LoanExtMapper;
import com.car.loan.project.xr.service.ILoanService;
import com.car.loan.project.xr.service.ILoanStatusService;
import com.car.loan.project.xr.service.loan.payment.LoanPaymentService;
import com.car.loan.project.xr.util.bo.business.LoanBaseInfo;
import com.car.loan.project.xr.util.bo.business.payment.PaymentInfoBo;
import com.car.loan.project.xr.util.bo.business.payment.SettleAccountsBo;
import com.car.loan.project.xr.util.enums.FileAuditStatus;
import com.car.loan.project.xr.util.enums.LicenseInfoStatus;
import com.car.loan.project.xr.util.enums.MakeLoansInfoStatus;
import com.car.loan.project.xr.util.enums.MortgageInfoStatus;
import com.car.loan.project.xr.util.enums.PaymentInfoStatus;
import com.car.loan.project.xr.util.enums.PaymentSettleAccountsStatus;
import com.car.loan.project.xr.util.select.LoanBasePageParam;
import com.car.loan.project.xr.util.vo.PaymentApplyVo;
import com.car.loan.project.xr.util.vo.pdf.SettlementPdf;
import com.itextpdf.text.DocumentException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author huangding
 * @description
 * @date 2019/11/26 17:05
 */
@RestController
@RequestMapping("xr/settle/accounts")
@Api(value = "结算信息", tags = "车贷业务-结算信息")
public class SettleAccountsController {


    @Autowired
    private LoanPaymentService loanPaymentService;

    @Autowired
    private ILoanService loanService;

    @Autowired
    private ILoanStatusService loanStatusService;


    @PreAuthorize("@ss.hasPermi('settle:accounts:list')")
    @GetMapping("list")
    @ApiOperation(value = "获取结算信息列表", response = LoanBaseInfo.class, responseContainer = "list")
    @DataStatus(loanStatusEnum = com.car.loan.common.enums.LoanStatusEnum.SETTLE_ACCOUNTS_STATUS)
    public AjaxResult applyList(@Valid LoanBasePageParam loanBasePageParam) {
        return AjaxResult.success(loanService.page(loanBasePageParam));
    }


    @PreAuthorize("@ss.hasPermi('settle:accounts:query')")
    @GetMapping("{loanId}")
    @ApiOperation(value = "获取结算信息详情", response = PaymentApplyVo.class)
    public AjaxResult saveApply(@PathVariable Long loanId) {
        return loanPaymentService.info(loanId);
    }


    @PreAuthorize("@ss.hasPermi('settle:accounts:add')")
    @PostMapping("settleInfoWrite")
    @Log(title = "结算信息填写", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "结算信息填写", notes = "需打印付款审批单")
    public AjaxResult saveApply(@RequestBody @Valid SettleAccountsBo settleAccountsBo) {
        return loanPaymentService.settleAccountsInfoWrite(settleAccountsBo);
    }


    @PreAuthorize("@ss.hasPermi('settle:accounts:withdraw')")
    @PutMapping("withdraw/{loanId}")
    @Log(title = "撤回结算信息填写", businessType = BusinessType.WITHDRAW)
    @ApiOperation(value = "撤回结算信息填写", notes = "档案信息已审核后不可撤回")
    public AjaxResult withdrawApply(@PathVariable Long loanId) {
        Optional<LoanStatus> optionalLoanStatus = loanStatusService.getByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("业务状态数据异常请联系管理员"));
        if (FileAuditStatus.SUBMIT.status == loanStatus.getFileAuditStatus()) {
            return AjaxResult.error("档案信息已审核，不可撤回");
        }
        loanStatus.setSettleAccountsStatus((long) PaymentSettleAccountsStatus.INIT.status);
        loanStatusService.updateLoanStatus(loanStatus);
        return AjaxResult.success();
    }


    public String getCarNature(String carNature) {
        if (StringUtils.isNotEmpty(carNature)) {
            if ("1".equals(carNature)) {
                return "新车";
            } else if ("2".equals(carNature)) {
                return "二手车";
            } else {
                return "存量车";
            }
        }
        return carNature;
    }

    @Resource
    private LoanExtMapper loanExtMapper;

    @Resource
    private LoanDetailMapper loanDetailMapper;

    @Resource
    private ExcelFileUtil excelFileUtil;

    @Resource
    private CmBankMapper cmBankMapper;

    @Autowired
    protected HttpServletRequest request;


    @GetMapping("downloadPdf")
    @ApiOperation("下载PDF")
    @PreAuthorize("@ss.hasPermi('payment:info:downloadPdf')")
    @DataStatus(loanStatusEnum = com.car.loan.common.enums.LoanStatusEnum.SETTLE_ACCOUNTS_STATUS)
    public AjaxResult downloadPdf(@Valid LoanBasePageParam loanBasePageParam,
        HttpServletResponse response) {
        Page<LoanBaseInfo> page = loanService.page(loanBasePageParam);
        List<LoanBaseInfo> records = page.getRecords();
        if (records.size() == 0) {
            return AjaxResult.error("无数据");
        }
        List<Object> settlementPdfList = new ArrayList<>();
        List<String> loanIds = records.stream().map(LoanBaseInfo::getId)
            .collect(Collectors.toList());

        List<Long> bankIds = records.stream().map(LoanBaseInfo::getBankId)
            .collect(Collectors.toList());
        List<CmBank> cmBanks = cmBankMapper.selectBatchIds(bankIds);

        Map<Long, CmBank> bankMap = cmBanks.stream()
            .collect(Collectors.toMap(CmBank::getId, c -> c));

        QueryWrapper<LoanExt> queryWrapperExt = new QueryWrapper<>();
        queryWrapperExt.in("loan_id", loanIds);
        List<LoanExt> loanExts = loanExtMapper.selectList(queryWrapperExt);

        Map<Long, LoanExt> loanExtMap = loanExts.stream()
            .collect(Collectors.toMap(LoanExt::getLoanId, l -> l));

        QueryWrapper<LoanDetail> queryWrapperDetail = new QueryWrapper<>();
        queryWrapperDetail.in("loan_id", loanIds);
        List<LoanDetail> loanDetails = loanDetailMapper.selectList(queryWrapperDetail);

        Map<Long, LoanDetail> loanDetailMap = loanDetails.stream()
            .collect(Collectors.toMap(LoanDetail::getLoanId, l -> l));

        for (LoanBaseInfo record : records) {
            SettlementPdf settlementPdf = new SettlementPdf();
            settlementPdf.setCustomerName(record.getCustomerName());
            settlementPdf.setBusinessNo(record.getBusinessNo());
            settlementPdf
                .setCarType(record.getCarType() + "/" + getCarNature(record.getCarNature()));
            settlementPdf.setDealerName(record.getDealerName());
            settlementPdf.setBankName(record.getBankName());
            settlementPdf.setSellAmount(StringUtils.subZeroAndDot(record.getSellAmount()));
            settlementPdf
                .setInstallmentAmount(StringUtils.subZeroAndDot(record.getInstallmentAmount()));
            settlementPdf.setTerm(record.getTerm());
            settlementPdf
                .setFinancingAmount(StringUtils.subZeroAndDot(record.getFinancingAmount()));
            String id = record.getId();
            LoanExt loanExt = loanExtMap.get(Long.parseLong(id));
            LoanDetail loanDetail = loanDetailMap.get(Long.parseLong(id));
            settlementPdf.setSettleRate(loanDetail.getSettleRate() + "%");
            settlementPdf.setRate(loanExt.getRate() + "%");

            settlementPdf.setShouldAmount(StringUtils.subZeroAndDot(loanDetail.getShouldAmount()));
            settlementPdf
                .setDiscountRate(StringUtils.subZeroAndDot(loanDetail.getDiscountRate()) + "%");
            settlementPdf.setSalesmanFinedAmount(
                StringUtils.subZeroAndDot(loanDetail.getSalesmanFinedAmount()));

            //实结金额需计算=应结金额-扣罚金额
            settlementPdf.setSalesmanRebateAmount(StringUtils.subZeroAndDot(
                loanDetail.getShouldAmount() - loanDetail.getSalesmanFinedAmount()));
            //实付金额=融资金额-（分期金额*结算预留）-分期金额，需取整
            //结算费率-执行费率  结算预留 如小于等于取结算预留
            //如大于，实付金额=实结金额，不用计算了
            CmBank cmBank = bankMap.get(record.getBankId());
            BigDecimal multiply = new BigDecimal(loanExt.getInstallmentAmount())
                .multiply(new BigDecimal(cmBank.getSettlement())
                        .divide(new BigDecimal(100), MathContext.DECIMAL128),
                    MathContext.DECIMAL128);
            double v = new BigDecimal(loanExt.getFinancingAmount())
                .subtract(multiply, MathContext.DECIMAL128)
                .subtract(new BigDecimal(loanExt.getInstallmentAmount()),
                    MathContext.DECIMAL128)
                .setScale(6, BigDecimal.ROUND_HALF_UP)
                .setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
            if (v >= Double.parseDouble(settlementPdf.getSalesmanRebateAmount())) {
                settlementPdf.setSettleAmount(StringUtils.subZeroAndDot(v));
            } else {
                settlementPdf.setSettleAmount(settlementPdf.getSalesmanRebateAmount());
            }
            settlementPdf.setPaymentAccount(
                loanDetail.getSalesmanBankAccountName() + "/" + loanDetail.getSalesmanBankName()
                    + "/" + loanDetail.getSalesmanBankAccountNo());
            //应退=实付金额-实结金额
            String v1 = new BigDecimal(settlementPdf.getSettleAmount())
                .subtract(
                    new BigDecimal(settlementPdf.getSalesmanRebateAmount(), MathContext.DECIMAL128)
                        .setScale(6, BigDecimal.ROUND_HALF_UP)
                        .setScale(0, BigDecimal.ROUND_HALF_UP)).toString();
            //备注中应付金额=实结金额，实付金额就是表格中的实付金额，
            settlementPdf.setRemark(
                "应付金额：" + settlementPdf.getSalesmanRebateAmount() + "元，实付金额：" + settlementPdf
                    .getSettleAmount() + "元，应退金额：" + v1 + "元");
            settlementPdf.setUserInfo(record.getAdminName() + "(" + record.getDeptName() + ")");
            //状态备注
            settlementPdf.setStatusRemark(getStatusRemark(record));
            settlementPdfList.add(settlementPdf);
        }
        //模板
        try {
            String exportFileName = System.currentTimeMillis() + ".pdf";
            PdfUtil.downloadPdf(response, request, settlementPdfList, exportFileName,
                excelFileUtil.getTemplatePath("settlement.pdf"));
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
            return AjaxResult.error("下载失败" + e.getMessage());

        } catch (Exception e) {
            return AjaxResult.error("下载失败" + e.getMessage());
        }
        return null;
    }

    public String getStatusRemark(LoanBaseInfo loanBaseInfo) {
        //放贷信息己提交了，己放贷，未提交的，未放贷
        StringBuilder sb = new StringBuilder("放贷状态：");
        Long makeLoansInfoStatus = loanBaseInfo.getMakeLoansInfoStatus();
        if (MakeLoansInfoStatus.INIT.status == makeLoansInfoStatus) {
            sb.append("未放贷，");
        } else {
            sb.append("己放贷，");
        }
        //如上牌信息未提交，未上牌
        //上牌信息己提交，抵押信息未提交，未抵押
        //抵押信息己提交，己抵押
        sb.append("牌证状态：");
        Long licenseInfoStatus = loanBaseInfo.getLicenseInfoStatus();
        if (LicenseInfoStatus.INIT.status == licenseInfoStatus) {
            sb.append("未上牌");
        } else {
            Long mortgageInfoStatus = loanBaseInfo.getMortgageInfoStatus();
            if (MortgageInfoStatus.INIT.status == mortgageInfoStatus) {
                sb.append("未抵押");
            } else {
                sb.append("己抵押");
            }
        }
        return sb.toString();
    }

}
